package com.github.llyb120.sxmanage;

import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.CopyOnWriteArraySet;

import static com.github.llyb120.sxmanage.Util.RunScript;
import static com.github.llyb120.sxmanage.WebSocketConfig.online;

/**
 * @Author: Administrator
 * @Date: 2020/12/1 12:36
 */
@ServerEndpoint("/webSocket/{sid}")
@Component
public class WebSocketServer {

    private static Set<Session> connections = new ConcurrentHashSet<>();

    public static final String GET_LIST = "GET_LIST";
    public static final String START = "START";
    public static final String STOP = "STOP";
    public static final String RESTART = "RESTART";
    public static final String SYNC_ONLINE = "SYNC_ONLINE";


    @PostConstruct
    void init(){
        ThreadUtil.execute(() -> {
            for (;;){
                ThreadUtil.sleep(1000);
                broadcast(SYNC_ONLINE, online);
            }
        });
    }

    @SneakyThrows
    public static void send(Session session, String event, Object data){
        Map<String, Object> map = new HashMap<>();
        map.put("event", event);
        map.put("data", data);
        session.getBasicRemote().sendText(JSON.toJSONString(map));
    }

    @SneakyThrows
    private void broadcast(String event, Object data){
        for (Session connection : connections) {
            send(connection, event, data);
        }
    }


    //建立连接成功调用
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "sid") String userName){
        String token = session.getRequestParameterMap().get("token").get(0);
        if (token == null) {
            IoUtil.close(session);
            return;
        }
        if(!LoginController.tokens.contains(token)){
            IoUtil.close(session);
            return;
        }
        connections.add(session);
        System.out.println("opened");
        //构造configlist
        JSONArray arr = JSON.parseArray(JSON.toJSONString(WebSocketConfig.services));
        for (Object o : arr) {
            JSONObject obj = (JSONObject) o;
            for (String s : obj.keySet()) {
                if (s.equals("name")) {
                    continue;
                }
                obj.put(s, !StrUtil.isBlankIfStr(obj.get(s)));
            }
        }
        send(session, GET_LIST, arr);
        send(session, SYNC_ONLINE, online);
//        sessionPools.put(userName, session);
//        addOnlineCount();
//        System.out.println(userName + "加入webSocket！当前人数为" + onlineNum);
//        try {
//            sendMessage(session, "欢迎" + userName + "加入连接！");
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }

    public static ServiceConfig.Config findByName(String name){
        return WebSocketConfig.services.stream()
            .filter(e -> e.getName().equals(name))
            .findFirst()
            .orElse(null);
    }

    @OnMessage
    @SneakyThrows
    public void onMessage(Session session, String message){
        try{
        JSONObject object = JSON.parseObject(message);
        String event = object.getString("event");
        Object data = object.get("data");
        String name;
        ServiceConfig.Config config = null;
        switch (event){
            case START:
                name = (String) data;
                config = findByName(name);
                if(StrUtil.isBlank(config.getStart())){
                    return;
                }
                RunScript(config.getStart(), false);
                break;

            case RESTART:
                name = (String) data;
                config = findByName(name);
                if(StrUtil.isBlank(config.getRestart())){
                    return;
                }
                RunScript(config.getRestart(), false);
                break;

            case STOP:
                name = (String) data;
                config = findByName(name);
                if(StrUtil.isBlank(config.getStop())){
                    return;
                }
                RunScript(config.getStop(), false);
                break;
        }

        } catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(message);
    }

    @OnClose
    public void onClose(Session session){
        connections.remove(session);
    }

    @OnError
    public void onError(Session session, Throwable throwable){
        throwable.printStackTrace();
//        connections.remove(session);
    }
}
